﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using DotSpatial.Controls;
using DotSpatial.Data;

using DotSpatial.Symbology;

using DotSpatial.Topology;

using Point = System.Drawing.Point;


namespace HaGisPack
{
    class SelectAndMoveFun : FMapFunctionBase
    {


        public SelectAndMoveFun(IMap map, List<IFeatureLayer> LayerList)
            : base(map)
        {
            this._LayerList = LayerList;
        }

        private void Configure()
        { 
        }

        //所有图层
        private List<IFeatureLayer> _LayerList;
                
       

        # region 字段

        private bool _dragging; //选择标志
        private bool _Movedragging; //移动中标志
        private bool _UseMove = false;  //可移动标志

        private Point _mousePosition;

        private Dictionary<IFeature, IFeatureCategory> _activeFeatures;
        private Dictionary<IFeature, IFeatureCategory> _selectedFeatures = new Dictionary<IFeature, IFeatureCategory>();

        private Point _dragCoord; //选择、移动时的起始坐标


        # endregion

        # region 属性

        /// <summary>
        /// 选择的所有图形
        /// </summary>
        public Dictionary<IFeature, IFeatureCategory> SelectedFeatures
        {
            get { return this._selectedFeatures; }
            set { this._selectedFeatures = value; }
        }

                
        # endregion




        # region 方法


        protected override void OnDraw(MapDrawArgs e)
        {
            //if (_dragging == false) return;
            //if (_dragCoord == null) return;

            if (_dragging == true && _dragCoord != null) //处于选择状态
            {
                e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
                Rectangle SelectRect = new Rectangle(Math.Min(_dragCoord.X, _mousePosition.X), Math.Min(_dragCoord.Y, _mousePosition.Y), Math.Abs(_mousePosition.X - _dragCoord.X), Math.Abs(_dragCoord.Y - _mousePosition.Y));

                e.Graphics.DrawRectangle(Pens.Black, SelectRect);
            }

            if (this._Movedragging == true && this._dragCoord != null)  //处于移动状态
            {
                e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

                GraphicsPath gp = new GraphicsPath();
                Pen Blue = new Pen(Color.Blue, 2);


                foreach (Feature f in this._selectedFeatures.Keys)  //每个图层的每个Shape(Feature)
                {
                    List<Point> pts = new List<Point>();

                    foreach (Coordinate c in f.Coordinates)
                    {
                        Point pt = new Point();
                        pt.X = Map.ProjToPixel(c).X - this._dragCoord.X + this._mousePosition.X;
                        pt.Y = Map.ProjToPixel(c).Y - this._dragCoord.Y + this._mousePosition.Y;
                        pts.Add(pt);
                    }

                    if (f.FeatureType == FeatureType.Point)
                    {
                        gp.AddRectangle(new Rectangle(pts[0].X - 1, pts[0].Y - 1, 2, 2));
                    }

                    if (f.FeatureType == FeatureType.Line)
                    {
                        //e.Graphics.DrawLines(Blue, pts.ToArray());

                        GraphicsPath gp1 = new GraphicsPath();
                        gp1.AddLines(pts.ToArray());//先将直线填进一个GraphicsPath
                        gp.AddPath(gp1, false);   //再将这个GraphicsPath添加到另一个GraphicsPath，false表示两个直线之间没有关系
                    }
                    if (f.FeatureType == FeatureType.Polygon)
                    {
                        gp.AddPolygon(pts.ToArray());
                    }

                }
                    //Feature更新
                    //fl.DataSet.InitializeVertices();
                    //fl.DataSet.UpdateEnvelopes();


                e.Graphics.DrawPath(Blue, gp);

                Blue.Dispose();
                gp.Dispose();

                //map更新
                Map.Invalidate();
                Map.MapFrame.Initialize();  
            }

            base.OnDraw(e);
        
        
        }


        /// <summary>
        /// 使鼠标经过的和选中的Shape亮起来
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        private bool ShapeHighlight()
        {

            Rectangle SelectRect = new Rectangle(Math.Min(_dragCoord.X, _mousePosition.X), Math.Min(_dragCoord.Y, _mousePosition.Y), Math.Abs(_mousePosition.X - _dragCoord.X), Math.Abs(_mousePosition.Y - _dragCoord.Y));
            IEnvelope ext = Map.PixelToProj(SelectRect).ToEnvelope();
            IPolygon env = ext.ToPolygon();           

            bool requiresInvalidate = false;

            foreach (IFeatureLayer fl in this._LayerList)
            {
                IFeatureSet _featureSet = fl.DataSet;
                foreach (IFeature feature in _featureSet.Features)
                {
                    if (_featureSet.FeatureType == FeatureType.Point)
                    {
                        MapPointLayer mpl = fl as MapPointLayer;

                        if (mpl != null)
                        {
                            if (ext.Contains(feature.Coordinates[0]))  //本句判断是不是选择的这个Feature，以下代码用来表现选择的Feature
                            {

                                IFeatureCategory oldCategory = mpl.GetCategory(feature);
                                 this._activeFeatures.Add(feature, oldCategory);

                                 IFeatureCategory selectedCategory = new PointCategory();

                                 selectedCategory.CopyProperties(oldCategory);  //这一句不一样???
                                 selectedCategory.SetColor(Color.FromArgb(255, 0, 0));
                                 selectedCategory.LegendItemVisible = false;

                                 mpl.SetCategory(feature, selectedCategory);

                                //mpl.SetCategory(_activeFeature[_activeFeature.Count - 1], _selectedCategory);  //选中Feature后，改变一下类型
                            }
                        }
                        requiresInvalidate = true;
                    }
                    else
                    {
                        if (feature.Intersects(env))  //本句判断是不是选择的这个Feature，以下代码只是用来表现此Feature与其它Feature的不同
                        {
                           
                            IFeatureCategory oldCategory = fl.GetCategory(feature);
                            this._activeFeatures.Add(feature, oldCategory);

                            IFeatureCategory newCategory = oldCategory;

                            if (_featureSet.FeatureType == FeatureType.Polygon)
                            {
                                //newCategory = oldCategory as PolygonCategory;

                                newCategory = new PolygonCategory(Color.FromArgb(55, 255, 0, 0), Color.Red, 1);
                                newCategory.LegendItemVisible = false;

             

                            }
                            if (_featureSet.FeatureType == FeatureType.Line)
                            {
                                //newCategory = oldCategory as LineCategory;

                                newCategory = new LineCategory(Color.Red, 3);
                                newCategory.LegendItemVisible = false;

                            }

                            fl.SetCategory(feature, newCategory);     //这个_activeCategory与_selectedCategory作用一样，类型一样，为什么要写成两个？？？？                    

                        }

                    }

                }
            }

            return requiresInvalidate;        

        }


        /// <summary>
        /// 鼠标离开Shape后，Shap要恢复正常
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        public void ShapeRemoveHighlight()
        {
            if (this._selectedFeatures == null || this._selectedFeatures.Count == 0) return; //没有Shape被点亮


            //有Shape被点亮，则将点亮的Shape赋回原来的类型

            //bool requiresInvalidate = false;

            foreach (IFeatureLayer fl in this._LayerList)
            {
                IFeatureSet fs=fl.DataSet as IFeatureSet ;

                foreach (IFeature f in fs.Features)
                {
                    if (this._activeFeatures.ContainsKey(f) == true)
                    {
                        fl.SetCategory(f, _activeFeatures[f]);
                    }
                }
            }

            this._activeFeatures.Clear();
            this._selectedFeatures.Clear();

            Map.MapFrame.Initialize();
            Map.Invalidate();

        }

                

        protected override void OnMouseMove(GeoMouseArgs e)
        {
            _mousePosition = e.Location;

            if (this._Movedragging == false)  //不在移动状态
            {

                //如果已经选择了Feature
                if (this._selectedFeatures != null && this._selectedFeatures.Count > 0)
                {
                    Rectangle mouseRect = new Rectangle(_mousePosition.X - 3, _mousePosition.Y - 3, 6, 6);
                    IEnvelope ext = Map.PixelToProj(mouseRect).ToEnvelope();
                    IPolygon env = ext.ToPolygon();


                    //当鼠标经过任意一个已选的Feature的时候，鼠标变为Hand,可移动状态
                    foreach (IFeature f in this._selectedFeatures.Keys)
                    {
                        if (f.FeatureType == FeatureType.Point)
                        {
                            if (ext.Contains(f.Coordinates[0]))
                            {
                                this.Map.Cursor = Cursors.Hand;
                                this._UseMove = true; //变成可移动状态
                                break;
                            }
                            else
                            {
                                this.Map.Cursor = new Cursor(@"F:\MapWindow6\mapwindow6_dbc476e1b259\MapWindow6Orlando\Resources\select.ico");
                                this._UseMove = false;
                            }
                        }
                        else
                        {
                            if (f.Intersects(env))
                            {
                                this.Map.Cursor = Cursors.Hand;
                                this._UseMove = true;  //变成可移动状态
                                break;
                            }
                            else
                            {
                                this.Map.Cursor = new Cursor(@"F:\MapWindow6\mapwindow6_dbc476e1b259\MapWindow6Orlando\Resources\select.ico");
                                this._UseMove = false;
                            }
                        }
                    }
                }
            }
            else  //在移动状态
            {
                this.Map.Cursor = Cursors.Hand;                    
            }

            Rectangle invilid = new Rectangle(Math.Min(_dragCoord.X, _mousePosition.X), Math.Min(_dragCoord.Y, _mousePosition.Y), Math.Abs(_mousePosition.X - _dragCoord.X), Math.Abs(_dragCoord.Y - _mousePosition.Y));
            invilid.Inflate(20, 20);
            Map.Invalidate(invilid);     
            base.OnMouseMove(e);
                     
        }

        protected override void OnMouseDown(GeoMouseArgs e)
        {

            Map.MapFrame.Initialize();
            Map.Invalidate();

            if (this._UseMove == false) //不在可移动状态，在选择状态
            {
                //所有选择的图形赋回原来的属性（颜色，线宽等）
                if (this._selectedFeatures.Count > 0)
                {
                    foreach (IFeatureLayer fl in this._LayerList)
                    {
                        IFeatureSet fs = fl.DataSet as IFeatureSet;
                        foreach (IFeature f in fs.Features)
                        {
                            if (this._selectedFeatures.ContainsKey(f))
                            {
                                fl.SetCategory(f, this._selectedFeatures[f]);
                            }
                        }
                    }
                }
                _dragging = true; 
                this._activeFeatures = new Dictionary<IFeature, IFeatureCategory>();
                this._selectedFeatures = new Dictionary<IFeature, IFeatureCategory>();
            }
            else  //在可移动状态
            {
                this._Movedragging = true;  //状态变为移动状态
            }
            
            _dragCoord = e.Location;
                                  
        }


        protected override void OnMouseUp(GeoMouseArgs e)
        {
            //只要是MouseUp,选择和移动都结束

            if (_dragging == true)   
            {
                _dragging = false; //选择结束
                this.ShapeHighlight();  //点亮选中的Shape
                if (this._selectedFeatures.Count == 0)  //这个if是为了解决双击标题栏而引起的MouseUp事件的Bug
                {
                    foreach (KeyValuePair<IFeature, IFeatureCategory> f in this._activeFeatures)
                    {
                        this._selectedFeatures.Add(f.Key, f.Value);
                    }
                }
            }

            if (this._Movedragging == true)  
            {
                this._Movedragging = false; //移动结束
                
                foreach (Feature f in this._selectedFeatures.Keys)
                {
                    List<Coordinate> newcoors = new List<Coordinate>();

                    //设置当前图层，这一句是必须有的……因为现在是多图层选择！！！！！！！！！！
                    this.Parent.Parent.LayerSys.SetCurrentLayer(f.ParentFeatureSet.DataTable.TableName);
                    //得到已选择的、要移动的shp
                    FShape OldShp = (this.Parent.Parent.LayerSys.CurrentLayer as FShapeLayer).GetShapeByID(f.DataRow["id"].ToString());

                    //因为是引用传递，将旧的Shp的所有属性赋给新的shp,不能直接等于！
                    FShape NewShp = new FShape(OldShp.Id);
                    foreach (Coordinate c in OldShp.normalPts)
                    {
                        Coordinate coor = new Coordinate(c.X, c.Y);
                        NewShp.normalPts.Add(coor);
                    }
                    foreach (Coordinate c in OldShp.KeyPts)
                    {
                        Coordinate coor = new Coordinate(c.X, c.Y);
                        NewShp.KeyPts.Add(coor);
                    }
                    NewShp.LayerName = OldShp.LayerName;

                    //赋完旧的属性后，修改自定义Fshape移动后的坐标
                    foreach (Coordinate c in NewShp.normalPts)
                    {
                        c.X = c.X + Map.PixelToProj(this._mousePosition).X - Map.PixelToProj(this._dragCoord).X;
                        c.Y = c.Y + Map.PixelToProj(this._mousePosition).Y - Map.PixelToProj(this._dragCoord).Y;
                    }

                    //本来关键点也应该修改坐标的，但是normalPts与关键点之间也是引用传递的关系，所以不能修改
                    //不知道是不是应该把normalPts与关键点分开，不应是引用传递的相等的关系？？？？？？？？？？
                    //foreach (Coordinate c in NewShp.KeyPts)
                    //{
                    //    c.X = c.X + Map.PixelToProj(this._mousePosition).X - Map.PixelToProj(this._dragCoord).X;
                    //    c.Y = c.Y + Map.PixelToProj(this._mousePosition).Y - Map.PixelToProj(this._dragCoord).Y;
                    //}
                                       

                    this.OnShapeChanged(NewShp);

                }

                //Feature更新
                foreach (IFeatureLayer fl in this._LayerList)
                {
                    fl.DataSet.InitializeVertices();
                    fl.DataSet.UpdateExtent();
                }
            }

            //this.Parent.SelectedFeatures.Clear();
            //foreach (Feature f in this._selectedFeatures.Keys)
            //{               
            //    this.Parent.SelectedFeatures.Add(f);
            //}

            Map.MapFrame.Initialize();
                
        }


        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                if (this._Movedragging == true)  //如果正在移动
                {
                    this._Movedragging = false; //结束移动

                    //Feature更新
                    //foreach (IFeatureLayer fl in this._LayerList)
                    //{
                    //    fl.DataSet.InitializeVertices();
                    //    fl.DataSet.UpdateEnvelopes();
                    //}
                }

                if (this._dragging == true)
                {
                    this._dragging = false;  //结束选择
                    this.Map.Invalidate();
                    this.Map.MapFrame.Initialize();
                }
 
            }

            base.OnKeyDown(e);
        }
        
        # endregion







    }
}
